// +FHDR------------------------------------------------------------
//                 Copyright (c) 2024 NOVAUTO.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : async_ver_1bit_delay.v
// Author        : ICer
// Created On    : 2024-11-29 11:10
// Last Modified : 2024-11-29 11:31 by ICer
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

`define module_urandom_define \
string   path_str; \
initial  path_str = $psprintf(path_str, "%m"); \
\
function integer urandom; \
  integer seed, i; \
  begin \
    seed = $urandom(); \
    for(i=path_str.len; i>=0; i=i-1)begin \
      seed = seed ^ path_str.getc(i); \
      seed = $urandom(seed); \
    end \
    urandom = $abs(seed); \
  end \
endfunction \
function integer urandom_range(); \
  input integer min, max; \
  integer seed, i; \
  begin \
    seed = $urandom(); \
    for(i=path_str.len; i>=0; i=i-1)begin \
      seed = seed ^ path_str.getc(i); \
      seed = $urandom(seed); \
    end \
    urandom_range = min + $abs(seed % (max - min)); \
  end \
endfunction

module async_ver_1bit_delay #(
    //parameter
)( /*AUTOARG*/
   // Outputs
   o_data,
   // Inputs
   i_clk, i_rst_n, i_data, o_clk, o_rst_n
   );

// ----------------------------------------------------------------
// Interface declare
// ----------------------------------------------------------------
input  i_clk;
input  i_rst_n;
input  i_data;

input  o_clk;
input  o_rst_n;
output o_data;
// ----------------------------------------------------------------
// Wire declare
// ----------------------------------------------------------------
`module_urandom_define

// ----------------------------------------------------------------
// AUTO declare
// ----------------------------------------------------------------
/*AUTOOUTPUT*/
/*AUTOINPUT*/
/*AUTOWIRE*/

// ----------------------------------------------------------------
// gain jump point
// ----------------------------------------------------------------
reg i_data_i_ff;
always @(posedge i_clk or negedge i_rst_n) begin
  if(i_rst_n == 1'b0)begin
    i_data_i_ff <= 1'b0;
  end
  else begin
    i_data_i_ff <= i_data;
  end
end

reg i_data_o_ff;
always @(posedge o_clk or negedge o_rst_n) begin
  if(o_rst_n == 1'b0)begin
    i_data_o_ff <= 1'b0;
  end
  else begin
    i_data_o_ff <= i_data;
  end
end

wire i_data_hold = (i_data == i_data_i_ff) || (i_data == i_data_o_ff);
wire i_data_jump = !i_data_hold;

// ----------------------------------------------------------------
// i_data -> o_data_ff1 -> o_data_ff2
// ----------------------------------------------------------------
reg o_data_ff1, o_data_ff2;
always @(posedge o_clk or negedge o_rst_n) begin
  if(o_rst_n == 1'b0)begin
    o_data_ff1 <= 1'b0;
  end
  else begin
    if(i_data_jump)begin
      if(urandom_range(1,10) >= 5)begin
        o_data_ff1 <= !i_data;
      end
      else begin
        o_data_ff1 <= i_data;
      end
    end
  end
end

always @(posedge o_clk or negedge o_rst_n) begin
  if(o_rst_n == 1'b0)begin
    o_data_ff2 <= 1'b0;
  end
  else begin
    o_data_ff2 <= o_data_ff1;
  end
end

assign o_data = o_data_ff2;

endmodule
// Local Variables:
// verilog-auto-inst-param-value:t
// verilog-library-directories:(".")
// verilog-library-extensions:(".v")
// End:

